/**
 * ControladoraBDMateria.java
 */

/**
 *  AdSec: Administrador de Secundarias
 *  Copyright (C) 2009 Daniela Ramírez Chaves (dannyrch@gmail.com)
 *  Copyright (C) 2009 Leonel Salazar Valverde (leo87sv@gmail.com)
 *
 *  This file is part of AdSec.
 *  AdSec is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  AdSec is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with AdSec.  If not, see <http://www.gnu.org/licenses/>.
 */

package adsec.datos;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.LinkedList;
import adsec.entidades.Materia;


public class ControladoraBDMateria {

    private Connection conexion;
    private AdministradorConexion adminConexion;

    public ControladoraBDMateria(){
        adminConexion = AdministradorConexion.getInstancia();
    }

    public Materia consultarMateria(int idMateria){
        Materia materia = null;
        conexion = adminConexion.getConexion();
        if(conexion != null){
            CallableStatement procedimiento = this.spConsultarMateria(conexion, idMateria);
            if(procedimiento != null){
                try{
                    procedimiento.execute();
                    ResultSet resultado = procedimiento.getResultSet();
                    if(resultado.next()){
                        materia = this.crearMateria(resultado);
                    }
                }catch(SQLException e){
                    e.printStackTrace();
                }//fin de try catch
            }//fin de if
        }//fin de if
        adminConexion.cerrarConexion();
        return materia;
    }//fin de consultarMateria

    public LinkedList<Materia> consultarMaterias(){
        LinkedList<Materia> lista = new LinkedList<Materia>();
        conexion = adminConexion.getConexion();
        if(conexion != null){
            CallableStatement procedimiento = this.spConsultarMaterias(conexion);
            if(procedimiento != null){
                try{
                    procedimiento.execute();
                    ResultSet resultado = procedimiento.getResultSet();
                    while(resultado.next()){
                        Materia materia = this.crearMateria(resultado);
                        lista.add(materia);
                    }//fin de while
                }catch(SQLException e){
                    e.printStackTrace();
                }//fin de try catch
            }//fin de if
        }//fin de if
        adminConexion.cerrarConexion();
        return lista;
    }//fin de consultarMaterias

    public LinkedList<Materia> consultarMateriasNivel(int nivel){
        LinkedList<Materia> lista = new LinkedList<Materia>();
        conexion = adminConexion.getConexion();
        if(conexion != null){
            CallableStatement procedimiento = this.spConsultarMateriasNivel(conexion, nivel);
            if(procedimiento != null){
                try{
                    procedimiento.execute();
                    ResultSet resultado = procedimiento.getResultSet();
                    while(resultado.next()){
                        Materia materia = this.crearMateria(resultado);
                        lista.add(materia);
                    }//fin de while
                }catch(SQLException e){
                    e.printStackTrace();
                }//fin de try catch
            }//fin de if
        }//fin de if
        adminConexion.cerrarConexion();
        return lista;
    }//fin de consultarMateriasNivel

    public LinkedList<Materia> consultarRequisitosMateria(int idMateria){
        LinkedList<Materia> lista = new LinkedList<Materia>();
        conexion = adminConexion.getConexion();
        if(conexion != null){
            CallableStatement procedimiento = this.spConsultarRequisitosMateria(conexion, idMateria);
            if(procedimiento != null){
                try{
                    procedimiento.execute();
                    ResultSet resultado = procedimiento.getResultSet();
                    LinkedList<Integer> listaRequisitos = new LinkedList<Integer>();
                    while(resultado.next()){
                        listaRequisitos.add(resultado.getInt(1));
                    }//fin de while
                    Iterator<Integer> iterador = listaRequisitos.iterator();
                    while(iterador.hasNext()){
                        Materia materia = this.consultarMateria(iterador.next().intValue());
                        lista.add(materia);
                    }//fin de while
                }catch(SQLException e){
                    e.printStackTrace();
                }//fin de try catch
            }//fin de if
        }//fin de if
        adminConexion.cerrarConexion();
        return lista;
    }//fin de consultarRequisitosMateria

    public int insertarMateria(Materia materia, LinkedList<Materia> materiasRequisito){
        int resultado = AdministradorConexion.QUERY_ERROR;
        conexion = adminConexion.getConexion();
        if(conexion != null){
            CallableStatement procedimiento = this.spInsertarMateria(conexion, materia);
            if(procedimiento != null){
                try{
                    procedimiento.execute();
                    ResultSet resultadoIDMateria = procedimiento.executeQuery("SELECT LAST_INSERT_ID()");
                    if(resultadoIDMateria.next() && materiasRequisito.size() > 0){
                        int idMateria = resultadoIDMateria.getInt(1);
                        if(idMateria > 0){
                            resultado = this.insertarRequisitos(idMateria, materiasRequisito);
                        }
                    }//fin de if
                    else{
                        resultado = AdministradorConexion.QUERY_OK;
                    }
                }catch(SQLException e){
                    e.printStackTrace();
                }//fin de try catch
            }//fin de if
        }//fin de if
        adminConexion.cerrarConexion();
        return resultado;
    }//fin de insertarMateria

    public int insertarRequisitos(int idMateria, LinkedList<Materia> materiasRequisito){
        int resultado = AdministradorConexion.QUERY_ERROR;
        conexion = adminConexion.getConexion();
        if(conexion != null){
            Iterator<Materia> iterador = materiasRequisito.iterator();
            while(iterador.hasNext()){
                Materia materia = iterador.next();
                CallableStatement procedimiento = this.spInsertarRequisito(conexion, idMateria, materia.getIdMateria());
                if(procedimiento != null){
                    try{
                        procedimiento.execute();
                    }catch(SQLException e){
                        e.printStackTrace();
                    }//fin de try catch
                }//fin de if
            }//fin de while
            resultado = AdministradorConexion.QUERY_OK;
        }//fin de if
        adminConexion.cerrarConexion();
        return resultado;
    }//fin de insertarMateria

    public int modificarMateria(Materia materia, LinkedList<Materia> materiasRequisito){
        int resultado = AdministradorConexion.QUERY_ERROR;
        conexion = adminConexion.getConexion();
        if(conexion != null){
            CallableStatement procedimiento = this.spModificarMateria(conexion, materia);
            if(procedimiento != null){
                try{
                    procedimiento.execute();
                    if(materiasRequisito.size() > 0){
                        procedimiento = this.spEliminarRequisitos(conexion, materia.getIdMateria());
                        procedimiento.execute();
                        resultado = this.insertarRequisitos(materia.getIdMateria(), materiasRequisito);
                    }//fin de if
                    else{
                        resultado = AdministradorConexion.QUERY_OK;
                    }//fin de else
                }catch(SQLException e){
                    e.printStackTrace();
                }//fin de try catch
            }//fin de if
        }//fin de if
        adminConexion.cerrarConexion();
        return resultado;
    }//fin de modificarMateria

    public int eliminarMateria(int idMateria){
        int resultado = AdministradorConexion.QUERY_ERROR;
        conexion = adminConexion.getConexion();
        if(conexion != null){
            CallableStatement procedimiento = this.spEliminarRequisitos(conexion, idMateria);
            if(procedimiento != null){
                try{
                    procedimiento.execute();
                    procedimiento = this.spEliminarMateria(conexion, idMateria);
                    procedimiento.execute();
                    resultado = AdministradorConexion.QUERY_OK;
                }catch(SQLException e){
                    e.printStackTrace();
                }//fin de try catch
            }//fin de if
        }//fin de if
        adminConexion.cerrarConexion();
        return resultado;
    }//fin de eliminarMateria

    private CallableStatement spConsultarMateria(Connection conexion, int idMateria){
        CallableStatement procedimiento = null;
        try{
            procedimiento = conexion.prepareCall("CALL consultarMateria" + UtilidadesCapaDatos.agregarParametros(1),
                ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            procedimiento.setInt(Materia.idMateriaNC + "_p", idMateria);
        }catch(SQLException sqlException){
            sqlException.printStackTrace();
        }
        return procedimiento;
    }//fin de spConsultarMateria

    private CallableStatement spConsultarMaterias(Connection conexion){
        CallableStatement procedimiento = null;
        try{
            procedimiento = conexion.prepareCall("CALL consultarMaterias()",
                ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        }catch(SQLException sqlException){
            sqlException.printStackTrace();
        }
        return procedimiento;
    }//fin de spConsultarMaterias

    private CallableStatement spConsultarMateriasNivel(Connection conexion, int nivel){
        CallableStatement procedimiento = null;
        try{
            procedimiento = conexion.prepareCall("CALL consultarMateriasNivel"+ UtilidadesCapaDatos.agregarParametros(1),
                ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            procedimiento.setInt(Materia.nivelNC + "_p", nivel );
        }catch(SQLException sqlException){
            sqlException.printStackTrace();
        }
        return procedimiento;
    }//fin de spConsultarMateriasNivel

    private CallableStatement spConsultarRequisitosMateria(Connection conexion, int idMateria){
        CallableStatement procedimiento = null;
        try{
            procedimiento = conexion.prepareCall("CALL consultarRequisitos"+ UtilidadesCapaDatos.agregarParametros(1),
                ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            procedimiento.setInt(Materia.idMateriaNC + "_p", idMateria );
        }catch(SQLException sqlException){
            sqlException.printStackTrace();
        }
        return procedimiento;
    }//fin de spConsultarMateriasNivel

    private CallableStatement spInsertarMateria(Connection conexion, Materia materia){
        CallableStatement procedimiento = null;
        try{
            procedimiento = conexion.prepareCall("CALL insertarMateria" + UtilidadesCapaDatos.agregarParametros(3),
                ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            procedimiento.setString(Materia.nombreNC + "_p", materia.getNombre());
            procedimiento.setInt(Materia.nivelNC + "_p", materia.getNivel());
            procedimiento.setInt(Materia.tipoMateriaNC + "_p", materia.getTipoMateria());
        }catch(SQLException sqlException){
            sqlException.printStackTrace();
        }
        return procedimiento;
    }//fin de spInsertarMateria

    private CallableStatement spInsertarRequisito(Connection conexion, int idMateria, int idRequisito){
        CallableStatement procedimiento = null;
        try{
            procedimiento = conexion.prepareCall("CALL insertarRequisito" + UtilidadesCapaDatos.agregarParametros(2),
                ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            procedimiento.setInt(Materia.idMateriaNC + "_p", idMateria);
            procedimiento.setInt(Materia.idRequisitoNC + "_p", idRequisito);
        }catch(SQLException sqlException){
            sqlException.printStackTrace();
        }
        return procedimiento;
    }//fin de spInsertarMateria

    private CallableStatement spModificarMateria(Connection conexion, Materia materia){
        CallableStatement procedimiento = null;
        try{
            procedimiento = conexion.prepareCall("CALL modificarMateria" + UtilidadesCapaDatos.agregarParametros(4),
                ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            procedimiento.setInt(Materia.idMateriaNC + "_p", materia.getIdMateria());
            procedimiento.setString(Materia.nombreNC + "_p", materia.getNombre());
            procedimiento.setInt(Materia.nivelNC + "_p", materia.getNivel());
            procedimiento.setInt(Materia.tipoMateriaNC + "_p", materia.getTipoMateria());
        }catch(SQLException sqlException){
            sqlException.printStackTrace();
        }
        return procedimiento;
    }//fin de spModificarMateria

    private CallableStatement spEliminarMateria(Connection conexion, int idMateria){
        CallableStatement procedimiento = null;
        try{
            procedimiento = conexion.prepareCall("CALL eliminarMateria" + UtilidadesCapaDatos.agregarParametros(1),
                ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            procedimiento.setInt(Materia.idMateriaNC + "_p", idMateria);
        }catch(SQLException sqlException){
            sqlException.printStackTrace();
        }
        return procedimiento;
    }//fin de spEliminarMateria

    private CallableStatement spEliminarRequisitos(Connection conexion, int idMateria){
        CallableStatement procedimiento = null;
        try{
            procedimiento = conexion.prepareCall("CALL eliminarRequisitos" + UtilidadesCapaDatos.agregarParametros(1),
                ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            procedimiento.setInt(Materia.idMateriaNC + "_p", idMateria);
        }catch(SQLException sqlException){
            sqlException.printStackTrace();
        }
        return procedimiento;
    }//fin de spEliminarRequisitos

    private Materia crearMateria(ResultSet resultSet) throws SQLException{
        Materia materia = new Materia();
        materia.setIdMateria(resultSet.getInt(Materia.idMateriaNC));
        materia.setNombre(resultSet.getString(Materia.nombreNC));
        materia.setNivel(resultSet.getInt(Materia.nivelNC));
        materia.setTipoMateria(resultSet.getInt(Materia.tipoMateriaNC));
        return materia;
    }//fin de crearMateria


}//fin de ControladoraBDMateria
